package com.hcnow.common.Exception.handle

import com.hcnow.common.Exception.AuthorizationException
import com.hcnow.common.Exception.CommonServerException
import com.hcnow.common.model.MessageBuilder
import com.hcnow.common.model.RestResponse
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.http.HttpStatus
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.*
import java.lang.reflect.InvocationTargetException
import javax.persistence.EntityNotFoundException

/**
 * 全局异常处理
 */
@RestControllerAdvice
class GlobalExceptionHandler(var messageBuilder: MessageBuilder) {

    val logger: Logger = LoggerFactory.getLogger(GlobalExceptionHandler::class.java);

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(CommonServerException::class)
    @ResponseBody
    fun handleCommonException(ex: CommonServerException): RestResponse<Unit> {
        ex.printStackTrace();
        logger.error(ex.toString());
        return RestResponse(false, Unit, messageBuilder.createMessage("server.error", arrayOf(ex.message)))
    }


    @ResponseStatus(value = HttpStatus.OK)
    @ExceptionHandler(MethodArgumentNotValidException::class)
    @ResponseBody
    fun handleValidationException(ex: MethodArgumentNotValidException): RestResponse<Unit> {
        val messages = ex.bindingResult.fieldErrors.map { it.defaultMessage }.toTypedArray()
        ex.printStackTrace();
        logger.error(ex.toString());
        return RestResponse(false, Unit, messageBuilder.createMessage("validation.error", messages))
    }

    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(AuthorizationException::class)
    @ResponseBody
    fun handleAuthorizationException(ex: AuthorizationException): RestResponse<Unit> {
        ex.printStackTrace();
        logger.error(ex.toString())
        return RestResponse(false, Unit, messageBuilder.createMessage("token.validation.error"))
    }


    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(DataIntegrityViolationException::class)
    @ResponseBody
    fun handleDataIntegrityViolationException(ex: DataIntegrityViolationException): RestResponse<Unit> {
        ex.printStackTrace();
        logger.error(ex.toString())
        return RestResponse(false, Unit, messageBuilder.createMessage("data.integrity.violation.error"))
    }

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(EntityNotFoundException::class)
    @ResponseBody
    fun handleDataIntegrityEntityNotFoundException(ex: EntityNotFoundException): RestResponse<Unit> {
        ex.printStackTrace();
        logger.error(ex.toString())
        return RestResponse(false, Unit,messageBuilder.createMessage("data.entity.not.found.error"));
    }

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(InvocationTargetException::class)
    @ResponseBody
    fun handleInvocationTargetException(ex: InvocationTargetException): RestResponse<Unit> {
        ex.printStackTrace();
        logger.error(ex.toString())
        return RestResponse(false, Unit,messageBuilder.createMessage("data.target.not.found.error"));
    }


    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(IllegalArgumentException::class)
    @ResponseBody
    fun handleIllegalArgumentException(ex: IllegalArgumentException): RestResponse<Unit> {
        ex.printStackTrace();
        logger.error(ex.toString())
        return RestResponse(false, Unit,messageBuilder.createMessage("illegal.argument.error"));
    }

}